home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_061 / vsprites / vsprite.final.c < prev   
C/C++ Source or Header  |  1992-05-06  |  17KB  |  607 lines

  1. /* vsprite.final.c, merged with its support files */
  2.  
  3. /* execute makesimple vsprite.final ; Amiga C 1.1 (Lattice 3.03) */
  4.  
  5. #include "exec/types.h"
  6. #include "intuition/intuition.h"
  7. #include "graphics/sprite.h"
  8. #include "exec/memory.h"
  9. #include "graphics/gels.h"
  10.  
  11. /* ask system to create and manage MAXSP vsprites */
  12. #define MAXSP 28 
  13.  
  14. /* define possible speeds for vsprites in counts per vblank */
  15.  
  16. SHORT speed[] = { 1, 2, -1, -2 };
  17.  
  18. SHORT xmove[MAXSP], ymove[MAXSP];      
  19.                 /* sprite directions of movement */
  20. struct VSprite *vsprite[MAXSP];    /* MAXSP simple sprites */
  21. struct VSprite *vspr;        /* pointer to a sprite */
  22. short maxgot;            /* max # of sprites we created */
  23.  
  24. struct GelsInfo mygelsinfo;    /* the window's RastPort needs one
  25.                  * of these in order to do VSprites */
  26.  
  27. struct Window *w;    /* pointer to a Window   */
  28. struct RastPort *rp;    /* pointer to a RastPort */
  29. struct Screen *s;    /* a pointer to a Screen */    
  30. struct ViewPort *vp;    /* pointer to a ViewPort */
  31.  
  32. struct Window *OpenWindow();
  33. struct Screen *OpenScreen();
  34. LONG GfxBase;
  35. LONG IntuitionBase;
  36.  
  37. /* 18 words of sprite data = 9 lines of sprite data */
  38.  
  39. UWORD sprite_data[ ] = {
  40.             0x0fc3, 0x0000, /* image data line 1*/
  41.             0x3ff3, 0x0000, /* image data line 2*/
  42.             0x30c3, 0x0000, /* image data line 3*/
  43.             0x0000, 0x3c03, /* image data line 4*/
  44.             0x0000, 0x3fc3, /* image data line 5*/
  45.             0x0000, 0x03c3, /* image data line 6*/
  46.             0xc033, 0xc033, /* image data line 7*/
  47.             0xffc0, 0xffc0, /* image data line 8*/
  48.             0x3f03, 0x3f03, /* image data line 9*/
  49.             };
  50. UWORD *sprdata;
  51.  
  52. void movesprites()
  53. {
  54.     short i;
  55.  
  56.     for (i=0; i<maxgot; i++)
  57.     {
  58.         vspr = vsprite[i];
  59.  
  60.         vspr->X = xmove[i]+vspr->X;
  61.         vspr->Y = ymove[i]+vspr->Y;
  62.  
  63.         /* move the sprites ... here. */
  64.  
  65.         if(vspr->X >= 300 || vspr->X <= 0) xmove[i]=-xmove[i];
  66.         if(vspr->Y >= 190 || vspr->Y <= 0) ymove[i]=-ymove[i];
  67.         
  68.     }
  69.     SortGList(rp);    /* get the list in order */
  70.     DrawGList(rp, vp);    /* create the sprite instructions */
  71.  
  72.     MakeScreen(s);  /* ask Intuition to pull it all together */
  73.     RethinkDisplay(); /* and to show us what we have now. */
  74. }
  75.  
  76.  
  77. #define AZCOLOR 1
  78. #define WHITECOLOR 2
  79.  
  80. #define WC WINDOWCLOSE
  81. #define WS WINDOWSIZING
  82. #define WDP WINDOWDEPTH
  83. #define WDR WINDOWDRAG
  84.  
  85. #define NORMALFLAGS (WC|WS|WDP)
  86. /* Did not use windowdrag because dont want screen to be moved. */
  87.  
  88. /* Allow window sizing so user can decrease size of window, then
  89.  * increase it again, thus erasing the background text and more
  90.  * easily see that some vsprites wink out and into existence when
  91.  * too many sprites are on a single horizontal plane and the
  92.  * vsprite machine runs out of sprites to assign.
  93.  */
  94.  
  95. /* myfont1 specifies characteristics of the default font;
  96.  * this case selects the 80 column font that displays as 
  97.  * 40 columns in low resolution mode.
  98.  */    
  99. struct TextAttr myfont1 = { "topaz.font", 8, 0, 0 };
  100.     
  101. struct NewScreen myscreen1 = {
  102.     0, 0,           /* LeftEdge, TopEdge ... where to put screen */
  103.     320, 200,     /* Width, Height ... size of the screen */
  104.     5,          /* 5 planes Depth, means 2 to the 5th or 
  105.                * 32 different colors to choose from once 
  106.               * the screen is opened.
  107.                */
  108.     1, 0,          /* DetailPen, BlockPen */
  109.     SPRITES,    /* ViewModes ... value of 0 = low resolution */
  110.     CUSTOMSCREEN,      /* Type of screen */
  111.     &myfont1,     /* Font to be used as default for this screen */
  112.     "32 Color Test", /* DefaultTitle for its title bar */
  113.     NULL,         /* screens user-gadgets, always NULL, ignored */
  114.     NULL };
  115.             /* address of custom bitmap for screen, 
  116.                 * not used in this example 
  117.                 */
  118.  
  119.  
  120. struct NewWindow myWindow = {
  121.     0,         /* LeftEdge for window measured in pixels, 
  122.                at the current horizontal resolution,
  123.                from the leftmost edge of the Screen */
  124.     0,        /* TopEdge for window is measured in lines 
  125.                from the top of the current Screen.   */
  126.     320, 185,    /* Width, Height of this window */ 
  127.     0,           /* DetailPen - what pen number is to be 
  128.                used to draw the borders of the window */ 
  129.     1,        /* BlockPen - what pen number is to be 
  130.                used to draw system generated window
  131.                gadgets */
  132.             /* (for DetailPen and BlockPen, the value
  133.                 of -1 says "use the default value")  */
  134.     CLOSEWINDOW,     /* simplesprite program used INTUITICKS also */
  135.             /* IDCMP Flags */
  136.     NORMALFLAGS | GIMMEZEROZERO | ACTIVATE,
  137.             /* Window Flags:  (see below for more info) */
  138.     NULL,        /* FirstGadget */
  139.     NULL,        /* CheckMark   */
  140.     "Click Close Gadget To Stop",    /* Window title */
  141.     NULL,        /* Pointer to Screen if not workbench */
  142.     NULL,        /* Pointer to BitMap if a SUPERBITMAP window */
  143.     320, 10,    /* minimum width, minimum height */
  144.     320, 200,    /* maximum width, maximum height */
  145.     CUSTOMSCREEN
  146.     };
  147.  
  148. #include "graphics/gfxmacros.h"
  149.  
  150. /* #include "event1.c"    */
  151. /* gets the event handler */
  152. /* event1.c */
  153.  
  154. HandleEvent(code)
  155.     LONG code;    /* provided by main */
  156. {
  157.     switch(code) 
  158.     {
  159.     case CLOSEWINDOW:
  160.         return(0);
  161.         break;
  162.     case INTUITICKS:    /* could have done much faster
  163.                  * but what the heck, this is
  164.                  * shorter for test purposes
  165.                  */
  166.         movesprites();    /* 10 moves per second; test */
  167.         default:
  168.             break;
  169.     }
  170. return(1);
  171. }
  172.  
  173. UWORD mycolortable[] = {
  174.  
  175.     0x0000, 0x0e30, 0x0fff, 0x0b40, 0x0fb0, 0x0bf0,
  176.     0x05d0, 0x0ed0, 0x07df, 0x069f, 0x0c0e,
  177.     0x0f2e, 0x0feb, 0x0c98, 0x0bbb, 0x07df, 
  178.  
  179.     0x0000, 0x0e30, 0x0fff, 0x0b40, 
  180.     0x0fb0, 0x0bf0, 0x05d0, 0x0ed0, 
  181.     0x07df, 0x069f, 0x0c0e, 0x0f2e, 
  182.     0x0feb, 0x0c98, 0x0bbb, 0x07df 
  183.     };
  184.  
  185.     /* black, red, white, fire-engine red, orange, yellow,
  186.     lime green, green, aqua, dark blue, purple,
  187.     violet, tan, brown, gray, skyblue, (everything again) */
  188.  
  189. UWORD colorset0[ ] = { 0x0e30, 0xffff, 0x0b40 }; /* same as colors 17-19 */
  190. UWORD colorset1[ ] = { 0x0bf0, 0x05d0, 0x0ed0 }; /* 21-23 */
  191. UWORD colorset2[ ] = { 0x069f, 0x0c0e, 0x0f2e }; /* 25-27 */
  192. UWORD colorset3[ ] = { 0x0c98, 0x0bbb, 0x07df }; /* 29-31 */
  193. UWORD *colorset[ ] = {
  194.             colorset0, colorset1,
  195.             colorset2, colorset3 };
  196. int choice;
  197. char *numbers[] = { "17","18","19",
  198.             "20","21","22","23",
  199.             "24","25","26","27",
  200.             "28","29","30","31" };
  201.  
  202. /* #include "ram:purgegels.c" */
  203. /* purgegels.c */
  204.  
  205. /*
  206.  * Use this to get rid of the gels stuff when it is not needed any more.
  207.  * You must have allocated the gels info stuff (use the ReadyGels routine).
  208.  */
  209.  
  210. void PurgeGels(g)
  211. struct GelsInfo *g;
  212. {
  213.    if (g->collHandler != NULL)
  214.       FreeMem(g->collHandler, sizeof(struct collTable));
  215.    if (g->lastColor != NULL)
  216.       FreeMem(g->lastColor, sizeof(LONG) * 8);
  217.    if (g->nextLine != NULL)
  218.       FreeMem(g->nextLine, sizeof(WORD) * 8);
  219.    if (g->gelHead != NULL)
  220.       FreeMem(g->gelHead, sizeof(struct VSprite));
  221.    if (g->gelTail != NULL)
  222.       FreeMem(g->gelTail, sizeof(struct VSprite));
  223. }
  224.  
  225.  
  226. /* Deallocate memory which has been allocated by the routines Makexxx. */
  227. /* Assumes images and imageshadow deallocated elsewhere. */
  228.  
  229. void DeleteGel(v)
  230. struct VSprite *v;
  231. {
  232.    if (v != NULL) {
  233.       if (v->VSBob != NULL) {
  234.          if (v->VSBob->SaveBuffer != NULL) {
  235.             FreeMem(v->VSBob->SaveBuffer, sizeof(SHORT) * v->Width
  236.                   * v->Height * v->Depth);
  237.          }
  238.          if (v->VSBob->DBuffer != NULL) {
  239.             if (v->VSBob->DBuffer->BufBuffer != 0) {
  240.                FreeMem(v->VSBob->DBuffer->BufBuffer,
  241.                      sizeof(SHORT) * v->Width * v->Height * v->Depth);
  242.             }
  243.             FreeMem(v->VSBob->DBuffer, sizeof(struct DBufPacket));
  244.          }
  245.          FreeMem( v->VSBob, sizeof(struct Bob));
  246.       }
  247.       if (v->CollMask != NULL) {
  248.          FreeMem(v->CollMask, sizeof(WORD) * v->Height * v->Width);
  249.       }
  250.       if (v->BorderLine != NULL) {
  251.          FreeMem(v->BorderLine, sizeof(WORD) * v->Width);
  252.       }
  253.       FreeMem(v, sizeof(struct VSprite));
  254.    }
  255. }
  256.  
  257. /* end of purgegels.c */
  258.  
  259. /* #include "ram:readygels.c" */
  260. /* readygels.c */
  261.  
  262. struct VSprite *SpriteHead = NULL;
  263. struct VSprite *SpriteTail = NULL;
  264.  
  265. void border_dummy()    /* a dummy collision routine */
  266.    return; 
  267. }
  268.  
  269. ReadyGels(g, r)
  270. struct RastPort *r;
  271. struct GelsInfo *g;
  272. {
  273.    /* Allocate head and tail of list. */
  274.    if ((SpriteHead = (struct VSprite *)AllocMem(sizeof
  275.          (struct VSprite), MEMF_PUBLIC | MEMF_CLEAR)) == 0) 
  276.    {
  277.       return(-1);
  278.    }
  279.  
  280.    if ((SpriteTail = (struct VSprite *)AllocMem(sizeof
  281.          (struct VSprite), MEMF_PUBLIC | MEMF_CLEAR)) == 0) 
  282.    {
  283.       FreeMem(SpriteHead, sizeof(struct VSprite));
  284.       return(-2);
  285.    }
  286.    g->sprRsrvd = 0xFC;    /* do not use sprites 0 or 1. */
  287.  
  288.    if ((g->nextLine = (WORD *)AllocMem(sizeof(WORD) * 8,
  289.          MEMF_PUBLIC | MEMF_CLEAR)) == NULL) 
  290.    {
  291.       FreeMem(SpriteHead, sizeof(struct VSprite));
  292.       FreeMem(SpriteTail, sizeof(struct VSprite));
  293.       return(-3);
  294.    }
  295.  
  296.   if ((g->lastColor = (WORD **)AllocMem(sizeof(LONG) * 8,
  297.          MEMF_PUBLIC | MEMF_CLEAR)) == NULL) 
  298.    {
  299.       FreeMem(g->nextLine,8 * sizeof(WORD));
  300.       FreeMem(SpriteHead, sizeof(struct VSprite));
  301.       FreeMem(SpriteTail, sizeof(struct VSprite));
  302.       return(-4);
  303.    }
  304.  
  305.   /* Next we prepare a table of pointers to the routines which should
  306.    * be performed when DoCollision senses a collision.  This
  307.    * declaration may not be necessary for a basic vsprite with
  308.    * no collision detection implemented, but then it makes for
  309.    * a complete example.
  310.    */
  311.    if ((g->collHandler = (struct collTable *)AllocMem(sizeof(struct
  312.          collTable), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) 
  313.    {
  314.       FreeMem(g->lastColor, 8 * sizeof(LONG));
  315.       FreeMem(g->nextLine,8 * sizeof(WORD));
  316.       FreeMem(SpriteHead, sizeof(struct VSprite));
  317.       FreeMem(SpriteTail, sizeof(struct VSprite));
  318.       return(-5);
  319.    }
  320.  
  321.   /* When any part of the object touches or passes across
  322.    * this boundary, it will cause the boundary collision
  323.    * routine to be called.  This is at smash[0] in the
  324.    * collision handler table and is called only if
  325.    * DoCollision is called.
  326.    */
  327.    g->leftmost = 0;
  328.    g->rightmost = r->BitMap->BytesPerRow * 8 - 1;
  329.    g->topmost = 0;
  330.    g->bottommost = r->BitMap->Rows - 1;
  331.  
  332.    r->GelsInfo = g;  /* Link together the two structures */
  333.  
  334.    InitGels(SpriteHead, SpriteTail, g );
  335.  
  336.   /* Pointers initialized to the dummy sprites which will be
  337.    * used by the system to keep track of the animation system.
  338.    */
  339.    SetCollision(0, border_dummy, g);
  340.    WaitTOF();
  341.    return(0);    /* a return value of 0 says all ok, any 
  342.          * negative value tells you when it failed.
  343.          * (see the listing as to what the routine
  344.          * was trying to do... all failures are
  345.          * due to out of memory conditions).
  346.          */
  347. }
  348.  
  349.  
  350. /* end of readygels.c */
  351.  
  352. /* #include "ram:MakeVSprite.c" */
  353. /* MakeVSprite.c */
  354.  
  355. struct VSprite *MakeVSprite(lineheight, image, colorset, x, y,
  356.                 wordwidth, imagedepth, flags)
  357. SHORT lineheight;    /* How tall is this vsprite? */
  358. WORD *image;        /* Where is the vsprite image data, should be
  359.                twice as many words as the value of lineheight */
  360. WORD *colorset;        /* Where is the set of three words which describes
  361.                the colors that this vsprite can take on? */
  362. SHORT x, y;        /* What is its initial onscreen position? */
  363. SHORT wordwidth, imagedepth, flags;
  364. {
  365.    struct VSprite *v;    /* Make a pointer to the vsprite structure which
  366.                this routine dynamically allocates */
  367.  
  368.    if ((v = (struct VSprite *)AllocMem(sizeof(struct VSprite),
  369.          MEMF_PUBLIC | MEMF_CLEAR)) == 0) 
  370.    {
  371.       return(0);
  372.    }
  373.  
  374.    v->Flags = flags;    /* Is this a vsprite, not a bob? */
  375.  
  376.    v->Y = y;        /* Establish initial position relative to */
  377.    v->X = x;        /* the Display coordinates. */
  378.  
  379.    v->Height = lineheight;    /* The Caller says how high it is. */
  380.    v->Width = wordwidth;   /* A vsprite is always 1 word (16 bits) wide. */
  381.  
  382.   /* There are two kinds of depth... the depth of the image itself, and the
  383.    * depth of the playfield into which it will be drawn. The image depth
  384.    * says how much data space will be needed to store an image if it's
  385.    * dynamically allocated. The playfield depth establishes how much space
  386.    * will be needed to save and restore the background when a bob is drawn.
  387.    * A vsprite is always 2 planes deep, but if it's being used to make a
  388.    * bob, it may be deeper...
  389.    */
  390.  
  391.    v->Depth = imagedepth;
  392.  
  393.   /* Assume that the caller at least has a default boundary collision
  394.    * routine.... bit 1 of this mask is reserved for boundary collision
  395.    * detect during DoCollision(). The only collisions reported will be
  396.    * with the borders. The caller can change all this later.
  397.    */
  398.  
  399.    v->MeMask = 1;
  400.    v->HitMask = 1;
  401.  
  402.    v->ImageData = image;    /* Caller says where to find the image. */
  403.  
  404.   /* Show system where to find a mask which is a squished down version
  405.    * of the vsprite (allows for fast horizontal border collision detect).
  406.    */
  407.  
  408.    if ((v->BorderLine = (WORD *)AllocMem((sizeof(WORD)*wordwidth),
  409.          MEMF_PUBLIC | MEMF_CLEAR)) == 0) 
  410.    {
  411.        FreeMem(v, sizeof(struct VSprite)); 
  412.        return(0);
  413.    }
  414.  
  415.   /* Show system where to find the mask which contains a 1 bit for any
  416.    * position in the object in any plane where there is a 1 bit (all planes
  417.    * OR'ed together).
  418.    */
  419.  
  420.    if ((v->CollMask = (WORD *)AllocMem(sizeof(WORD)*lineheight*wordwidth,
  421.          MEMF_CHIP | MEMF_CLEAR)) == 0) 
  422.    {
  423.        FreeMem(v, sizeof(struct VSprite)); 
  424.        FreeMem(v->BorderLine, wordwidth * sizeof(WORD));
  425.         return(0);
  426.    }
  427.  
  428.   /* This isn't used for a Bob, just a VSprite. It's where the
  429.    * Caller says where to find the VSprites colors.
  430.    */
  431.    v->SprColors = colorset;
  432.  
  433.    /* These aren't used for a VSprite, and MakeBob'll do set up for Bob. */
  434.    v->PlanePick  = 0x00;
  435.    v->PlaneOnOff = 0x00;
  436.  
  437.    InitMasks(v);    /* Create the collMask and borderLine */    
  438.    return(v);
  439. }
  440. /* end of MakeVSprite.c */
  441.  
  442. int main()
  443. {
  444.     struct IntuiMessage *msg;
  445.     LONG result;
  446.     SHORT k, j, x, y, error;
  447.     UWORD *src, *dest;    /* for copying sprite data to RAM */
  448.  
  449.     GfxBase = OpenLibrary("graphics.library",0);
  450.  
  451.     IntuitionBase = OpenLibrary("intuition.library",0);
  452.     /* (error checking left out for brevity here) */
  453.  
  454.     s = OpenScreen(&myscreen1);  /* try to open it */
  455.     if(s == 0)
  456.     {
  457.             printf("Can't open myscreen1\n");
  458.             exit(10);
  459.     }
  460.     myWindow.Screen = s;    /* say where screen is located */
  461.  
  462.     ShowTitle(s, FALSE);    /* Dont let screen be dragged down...*/
  463.  
  464.     w = OpenWindow(&myWindow);
  465.     if(w == 0)
  466.     {
  467.         printf("Window didn't open!\n");
  468.         CloseScreen(s);
  469.         exit(20);
  470.     }
  471.     vp = &(s->ViewPort);
  472.     /* set the colors for this viewport */
  473.  
  474.     LoadRGB4(vp, &mycolortable[0], 32);
  475.     rp = w->RPort;
  476.         /* Now wait for a message to arrive from Intuition 
  477.          * (task goes to sleep while waiting for the message) 
  478.          */
  479.  
  480.     /* Write Text using sprite colors so that demo can show
  481.      * how the vsprite machine stuffs the colors as it goes
  482.      * down the screen.  Thus if using vsprites, user should
  483.      * avoid using the color registers that the vsprites use.
  484.      */
  485.  
  486.     /* Notice also that color numbers 17-19 are untouched.  
  487.      * That is because of the sprResrvd=0xFC in ReadyGels.
  488.      * (Doesn't allow the virtual sprite machine to access
  489.      * either sprite 0 or 1... 0 is used by mouse cursor and
  490.      * shares its colors with 1, so I reserved both of them.
  491.      */
  492.  
  493.     for(j=8; j<180; j+=50)
  494.     {
  495.         for(k=0; k<15; k++)
  496.         {
  497.             Move(rp,k*20,j);
  498.             SetAPen(rp,k+17);    /* show 17-31 */
  499.             /* 16, 20, 24, 28 are unaffected by vsprites 
  500.              * because they are not used by hardware sprites */
  501.  
  502.             Text(rp,numbers[k],2);
  503.         }
  504.     }
  505.     /* *************************************** */
  506.     /* VSPRITE DEMO SECTION            */
  507.     /* *************************************** */
  508.  
  509.     /* Allocate CHIP memory to hold the actual sprite data */
  510.     /* (necessary if ever to run on an expanded RAM Amiga) */
  511.  
  512.     sprdata = (UWORD *)AllocMem(36, MEMF_CHIP);
  513.  
  514.     if(sprdata == NULL)
  515.     {
  516.         /* not enough memory for sprite */
  517.     }
  518.     /* now copy the sprite data into the CHIP RAM. */
  519.  
  520.     src = sprite_data;  
  521.     dest = sprdata;     /* source, destination */
  522.  
  523.     for( j=0; j<18; j++)
  524.     {
  525.         *dest++ = *src++;
  526.     }            
  527.  
  528.     choice = 0;
  529.     maxgot = 0;
  530.  
  531.     /* Prepare the GELS system to work with VSPRITE or BOBS */
  532.  
  533.     error = ReadyGels(&mygelsinfo, rp);
  534.  
  535.     for(k=0; k<MAXSP; k++)    /* whatever maximum number of vsprites */
  536.     {
  537.         xmove[k]=speed[RangeRand(4)];
  538.         ymove[k]=speed[RangeRand(4)];
  539.  
  540.         /* establish a position for the sprite */
  541.         x = 10 + RangeRand(280);
  542.         y = 10 + RangeRand(170);
  543.  
  544.         /* create a vsprite */
  545.         vsprite[k] = MakeVSprite( 9, sprdata, colorset[choice], 
  546.                     x, y, 1, 2, VSPRITE);
  547.         /* 9 lines high, using MEMF_CHIP image of a sprite,
  548.          * with a particular set of colors, at an X,Y location
  549.          * 1 word wide, 2 planes deep (all vsprites are 2 deep)
  550.          * and it is a VSPRITE */
  551.  
  552.         if(vsprite[k] == 0)
  553.         {
  554.             break;    /* ran out of memory! */
  555.         }
  556.         AddVSprite(vsprite[k], rp);
  557.  
  558.         maxgot++;
  559.  
  560.         choice++; /* choose a different color set */
  561.         if(choice >= 4) 
  562.         {
  563.             choice = 0;    /* wrap around on colorsets */
  564.         }
  565.     }
  566.     while(1)    /* forever */
  567.     {
  568.         WaitTOF();
  569.         movesprites();
  570.  
  571.         result = -1;    /* now see if CLOSEWINDOW is waiting */
  572.         msg = (struct IntuiMessage *)GetMsg(w->UserPort);        
  573.         if(msg != 0)
  574.         {
  575.             result = HandleEvent(msg->Class);
  576.  
  577.             /* Let Intuition reuse the msg */
  578.             ReplyMsg(msg);    
  579.         }
  580.         if(result == 0) 
  581.         {
  582.             break;  /* got a CLOSEWINDOW */
  583.         }
  584.     }
  585.  
  586.     /* DONE, now cleanup */
  587.  
  588.     /* Free however many vsprites we actually managed to create */
  589.  
  590.     for(k=0; k<maxgot; k++)
  591.     {
  592.         DeleteGel(vsprite[k]);                
  593.     }
  594.     /* delete what ReadyGels created */
  595.     PurgeGels(&mygelsinfo);    
  596.  
  597.     FreeMem(sprdata, 36);    /* free what we allocated. */
  598.  
  599.     CloseWindow(w);
  600.     CloseScreen(s);
  601.     return (0);
  602. }    
  603.  
  604.  
  605.  
  606.